#define _GNU_SOURCE
#include <stdio.h>         // 用于标准输入输出函数，如 printf
#include <stdlib.h>        // 用于内存分配函数，如 malloc, calloc, free
#include <string.h>        // 用于字符串操作函数，如 memset
#include <fcntl.h>         // 用于文件控制定义，如 O_RDONLY, O_NONBLOCK
#include <unistd.h>        // 用于POSIX操作系统API函数，如 close, read
#include <errno.h>         // 用于处理错误代码，如 errno
#include <sys/types.h>     // 用于定义数据类型，如 fd_set
#include <sys/select.h>    // 用于 select 函数及相关的FD_SET操作
#include <sys/time.h>      // 用于定义时间结构体，如 struct timeval
#include "../include/listop.h"          // 用于链表操作（假设list_head和list操作函数定义在这个文件中）
#include <pthread.h>       // 用于线程相关操作，如 pthread_exit
#include <linux/joystick.h> 
#include <stdbool.h>//允许你在 C 语言中使用布尔类型。
#include "../include/my_joystick.h"
#include "../include/commands.h"
#include "../include/log.h"
#include "../include/type.h"
#include "../include/uart.h"

// 操纵杆相关的全局变量定义
AXES_T* joystick_axes = NULL;     // 表示操纵杆轴的结构体指针
char* shared_memory_buffer = NULL;//共享内存
int ctr_mode = 0;
int ctr_mode_shift = 0;
int power_flag=0;

int joystick_fd = -1;  // 表示操纵杆文件描述符
int joystick_result_code = 0;//表示操纵杆相关操作返回的结果码
char joystick_num_axes = 0;//表示操纵杆的轴数量
char joystick_num_buttons = 0;//表示操纵杆的按钮数量
char joystick_name[128] = {0};  //表示操纵杆设备的名称
unsigned int joystick_button_state = 0; //表示操纵杆按钮的状态
 AXES_T*  joystick_axes_status = 0;//表示操纵杆初始化状态
struct js_event joystick_event;//表示操纵杆事件

// 全局变量
struct list_head _t_js_ctx_head = LIST_HEAD_INIT(_t_js_ctx_head);  // 操纵杆上下文链表

// 打开操纵杆设备
int joystick_open(const char* cp_js_dev_name, int i4_block) {
    int i4_open_flags = O_RDONLY;
    JOYSTICK_CTX_T* pt_joystick_ctx = NULL;

    if (!cp_js_dev_name) {
        LOG_ERR("[%s] Joystick device name is NULL", __func__);//__func__ 是一个预定义标识符，它会在编译时被替换为当前函数的名字。
        return -1;
    }

    pt_joystick_ctx = (JOYSTICK_CTX_T*)calloc(1, sizeof(JOYSTICK_CTX_T));  // 分配内存
    if (!pt_joystick_ctx) {
        LOG_ERR("[%s] No memory!", __func__);
        return -1;
    }

    pt_joystick_ctx->i4_op_block = i4_block ? 1 : 0;  // 设置是否阻塞
    if (pt_joystick_ctx->i4_op_block == 0) {
        i4_open_flags |= O_NONBLOCK;  // 非阻塞模式
    }

    pt_joystick_ctx->i4_js_fd = open(cp_js_dev_name, i4_open_flags);  // 打开操纵杆设备
    if (pt_joystick_ctx->i4_js_fd < 0) {
        LOG_ERR("[%s] Open device %s error", __func__, cp_js_dev_name);
        free(pt_joystick_ctx);
        return -1;
    }

    list_add_tail(&pt_joystick_ctx->list, &_t_js_ctx_head);  // 将设备添加到链表中
    LOG_INFO("Joystick device %s opened with fd: %d", cp_js_dev_name, pt_joystick_ctx->i4_js_fd);
    return pt_joystick_ctx->i4_js_fd;
}

// 关闭操纵杆设备
int joystick_close(int i4_fd) {
    struct list_head* pt_entry;
    struct list_head* pt_next;
    JOYSTICK_CTX_T* pt_node;

    if (list_empty(&_t_js_ctx_head)) {
        LOG_ERR("[%s] Device not opened", __func__);
        return -1;
    }

    list_for_each_safe(pt_entry, pt_next, &_t_js_ctx_head) {
        pt_node = list_entry(pt_entry, JOYSTICK_CTX_T, list);
        if (pt_node->i4_js_fd == i4_fd) {
            list_del_init(&pt_node->list);  // 从链表中删除节点
            free(pt_node);
            LOG_INFO("Joystick device with fd: %d closed", i4_fd);
            return close(i4_fd);
        }
    }

    LOG_ERR("[%s] Invalid file descriptor: %d", __func__, i4_fd);
    return -1;
}

// 读取操纵杆事件
int joystick_read_one_event(int i4_fd, struct js_event* tp_jse) {
    int i4_rd_bytes = read(i4_fd, tp_jse, sizeof(struct js_event));

    if (i4_rd_bytes == -1) {
        if (errno == EAGAIN) {  // 非阻塞模式下无数据时返回 0
            return 0;
        } else {
            con_flag = false;
            LOG_ERR("[%s] Read error on fd: %d", __func__, i4_fd);
            return -1;
        }
    }

    return i4_rd_bytes;  // 成功读取事件时返回字节数
}

// 判断操纵杆是否就绪
int joystick_read_ready(int i4_fd) {
    int i4_block = 2;
    struct list_head* pt_entry;
    JOYSTICK_CTX_T* pt_node;

    if (list_empty(&_t_js_ctx_head)) {
        LOG_ERR("[%s] Device not opened", __func__);
        return -1;
    }

    list_for_each(pt_entry, &_t_js_ctx_head) {
        pt_node = list_entry(pt_entry, JOYSTICK_CTX_T, list);
        if (pt_node->i4_js_fd == i4_fd) {
            i4_block = pt_node->i4_op_block;
            break;
        }
    }

    if (i4_block == 2) {
        LOG_ERR("[%s] Invalid file descriptor: %d", __func__, i4_fd);
        return 0;
    } else if (i4_block == 1) {  // 阻塞模式
        fd_set readfd;
        int i4_ret = 0;
        struct timeval timeout = {0, 0};
        FD_ZERO(&readfd);
        FD_SET(i4_fd, &readfd);

        i4_ret = select(i4_fd + 1, &readfd, NULL, NULL, &timeout);
        if (i4_ret > 0 && FD_ISSET(i4_fd, &readfd)) {
            return 1;
        } else {
            return 0;
        }
    }

    return 1;  // 非阻塞模式，始终返回就绪
}

// 调试函数：打印操纵杆链表信息
void debug_list(void) 
{
    if (!list_empty(&_t_js_ctx_head)) {
        struct list_head* pt_entry;
        JOYSTICK_CTX_T* pt_node;

        list_for_each(pt_entry, &_t_js_ctx_head) {
            pt_node = list_entry(pt_entry, JOYSTICK_CTX_T, list);
            LOG_DBG("fd: %d -- block: %d", pt_node->i4_js_fd, pt_node->i4_op_block);
        }
    } else {
        LOG_DBG("Joystick context list is EMPTY NOW");
    }
}



// 处理按钮事件
void process_button_event(int button_number, int value) 
{
    if (value) {  // 按钮按下事件
        switch (button_number) {
            case 4:
                motor_add_flag = 1;
                LOG_DBG("Motor add flag set to 1");
                break;
            case 0:
                motor_add_flag = 2;
                LOG_DBG("Motor add flag set to 2");
                break;
            case 1:
                stepmotor_add_flag = 1;
                LOG_DBG("Step motor add flag set to 1");
                break;
            case 3:
                stepmotor_add_flag = 2;
                LOG_DBG("Step motor add flag set to 2");
                break;
            /*case 6:
                if (ctr_mode == 0) {
                    set_servo_position(ctr_mode, 0);
                } else if (ctr_mode == 2) {
                    ctr_mode_shift = (ctr_mode_shift > 0) ? (ctr_mode_shift - 1) : 0;
                }
                break;
            case 7:
                if (ctr_mode == 0) {
                    set_servo_position(ctr_mode, 1);
                } else if (ctr_mode == 2) {
                    ctr_mode_shift = (ctr_mode_shift < 8) ? (ctr_mode_shift + 1) : 8;
                }
                break;*/
            case 11:  // 控制电源状态
                set_power((power_flag++ & 1) != 0);
                trans_flag = (power_flag & 1) != 0;
                break;
            case 13:
                memcpy(shared_memory_buffer, "record", SHMSIZE);
                LOG_INFO("Recording started");
                break;
            case 14:
                memcpy(shared_memory_buffer, "unrecord", SHMSIZE);
                LOG_INFO("Recording stopped");
                break;
            default:
                break;
        }
    } else {  // 按钮松开事件
        switch (button_number) {
            case 4:
            case 0:
                motor_add_flag = 0;
                break;
            case 1:
            case 3:
                stepmotor_add_flag = 0;
                break;
            default:
                break;
        }
    }
}

// 处理轴事件
void process_axis_event(const struct js_event* jse) 
{
    if (!joystick_axes) return;

    switch (ctr_mode) {
        case 0:
            if (jse->number / 2 == 0) {
                joystick_axes[jse->number / 2].x = jse->value;
                fin_left_out_add_flag = (jse->value > 0) ? 1 : (jse->value < 0) ? 2 : 0;
            } else if (jse->number / 2 == 1) {
                joystick_axes[jse->number / 2].y = jse->value;
                fin_left_in_add_flag = (jse->value > 0) ? 1 : (jse->value < 0) ? 2 : 0;
            }
            break;
        case 1:
            if (jse->number / 2 == 0) {
                joystick_axes[jse->number / 2].x = jse->value;
                host_ctr_cmd_g.servo_ctr.servo_head_x = 90 + (float)jse->value / 32767 * 45;
            } else if (jse->number / 2 == 1) {
                joystick_axes[jse->number / 2].y = jse->value;
                host_ctr_cmd_g.servo_ctr.servo_head_y = 90 - (float)jse->value / 32767 * 90;
            }
            break;
        default:
            break;
    }
    if (trans_flag) {
        uart_send_command(&host_ctr_cmd_g, sizeof(host_ctr_cmd_g));  // 发送数据
    }
}